package edu.whu.rose.clock.ssql.search;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.Iterator;
import java.util.StringTokenizer;

import edu.whu.rose.clock.kps.algorithm.banks1.AnswerTree;
import edu.whu.rose.clock.kps.algorithm.banks1.BackwardExpandingSearch;
import edu.whu.rose.clock.kps.graph.GraphMatrix;
import edu.whu.rose.clock.setup.IndexEnvironment;
import edu.whu.rose.clock.ssql.index.VertexIndexDB;

public class SearchManager {
	
	private VertexIndexDB vidb;
	
	private GraphMatrix graph;
	
	public static final int BANKS_1 = 1;
	
	public SearchManager(VertexIndexDB vidb, GraphMatrix graph) {
		this.vidb = vidb;
		this.graph = graph;
	}
	
	public static void main(String[] args) {
		IndexEnvironment ie = new IndexEnvironment("dbEnv_vertexindex");
		ie.openEnv();
		VertexIndexDB vidb = new VertexIndexDB(ie.getEnvironment());
		if (!vidb.openDB()) {
			System.exit(1);
		}
		
		GraphMatrix graph = new GraphMatrix(11012);
		graph.loadEdges("graph/edge.txt");
		
		SearchManager sm = new SearchManager(vidb, graph);
		
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		AnswerTree[] answers = null;
		try {
			while (true) {
				System.out.println("Please input query:");
				String statement = br.readLine().trim();
				if (!statement.equals("exit")) {
					Date startTime = new Date();
					answers = sm.search(SearchManager.BANKS_1, statement, 100);
					Date endTime = new Date();
					if (answers != null) {
						for (int i = 0; i < answers.length; i++) {
							AnswerTree at = answers[i];
							if (at == null) {
								break;
							}
							System.out.print("Rank " + (i + 1) + ": root[" + at.getRoot() + "] ");
							
							for (int j = 0; j < at.getLeafNumber(); j++) {
								int[] path = at.getPath(j);
								System.out.print("( ");
								if (path != null) {
									for (int m = 0; m < path.length; m++) {
										System.out.print(path[m] + ", ");
									}
								}
								System.out.print(" )");
							}
							System.out.println();
						}
						
						System.out.println("Time exhausted: " + (endTime.getTime() - startTime.getTime()) + " ms");
					}
					else {
						System.out.println("Sorry, no result is found.");
					}
				}
				else {
					break;
				}
			}
		}
		catch (IOException ex) {
			ex.printStackTrace();
		}
		
		vidb.closeDB();
		ie.closeEnv();
	}
	
	public AnswerTree[] search(int engine, String statement, int k) {
		StringTokenizer st = new StringTokenizer(statement);
		String[] keywords = new String[st.countTokens()];
		int i = 0;
		while (st.hasMoreTokens()) {
			keywords[i] = st.nextToken().trim();
			i++;
		}
		return search(engine, keywords, k);
	}
	
	public AnswerTree[] search(int engine, String[] keywords, int k) {
		int[][] groups = new int[keywords.length][];  // vertex groups for keywords
		for (int i = 0; i < keywords.length; i++) {
			int[] group = vidb.search(keywords[i]);
			groups[i] = group;
		}
		
		AnswerTree[] answers = null;
		switch (engine) {
		case BANKS_1 :
			BackwardExpandingSearch bes = new BackwardExpandingSearch(graph, groups, k);
			bes.init();
			bes.search();
			answers = bes.getAnswers();
			break;
		}
		
		return answers;
	}
}